import streamlit as st
import streamlit_antd_components as sac
import datetime
import ujson as json
import pandas as pd
from code_editor import code_editor
from data_utils import code_save_button_config
from authentication import load_config
from audit import get_calc_audit_logs
import matplotlib.pyplot as plt
from pdf_utils import generate_pdf_download_button, SYSTEM_FONT_PATH
from data_utils import (
    load_tasks,
    load_calculator_by_id,
    update_calculator,
    convert_numeric_type,
    init_excel_sheet,
    cleanup_excel,
    save_plot_as_base64,
    format_calc_result,
)

status_colors = {"draft": "yellow", "active": "green", "inactive": "red"}
status_icon = {
    "draft": sac.BsIcon(name="pause-fill"),
    "active": sac.BsIcon(name="play-fill"),
    "inactive": sac.BsIcon(name="stop-fill"),
}


def ensure_target_field(inputs):
    """确保所有输入字段都有target属性"""
    for field in inputs:
        if "target" not in field:
            field["target"] = None
    return inputs


def sort_targets(targets):
    """
    自定义排序函数:
    1. 将 None 转换为"其他"
    2. 去重
    3. 按规则排序("其他"在最前)
    """
    # 将 None 转换为"其他"并去重
    processed = set("其他" if x is None else x for x in targets)

    def sort_key(x):
        return (0, "") if x == "其他" else (1, x)

    return sorted(processed, key=sort_key)


def render_input_field(field, test_inputs, column):
    """渲染单个输入字段"""
    iname = field.get("name", "")
    title = field.get("title", "")
    ptype = field.get("type", "string")

    # 若input_mode为“非输入项”则直接返回
    if field.get("input_mode") == "非输入项":
        return

    with column:
        if ptype == "number":
            minimum = convert_numeric_type(field.get("minimum"), "number")
            maximum = convert_numeric_type(field.get("maximum"), "number")
            step = convert_numeric_type(field.get("step"), "number") or 0.1
            default = convert_numeric_type(field.get("default"), "number") or 0.0

            # 根据step值确定输入精度
            decimal_places = len(str(step).split(".")[-1]) if "." in str(step) else 0

            test_inputs[iname] = st.number_input(
                f"{iname} - {title}",
                min_value=minimum,
                max_value=maximum,
                step=step,
                value=default,
                format=f"%.{decimal_places}f",  # 设置显示精度
            )
        elif ptype == "integer":
            minimum = convert_numeric_type(field.get("minimum"), "integer")
            maximum = convert_numeric_type(field.get("maximum"), "integer")
            step = convert_numeric_type(field.get("step"), "integer") or 1
            default = convert_numeric_type(field.get("default"), "integer") or 0
            test_inputs[iname] = st.number_input(
                f"{iname} - {title}",
                min_value=minimum,
                max_value=maximum,
                step=step,
                value=default,
            )
        else:
            test_inputs[iname] = st.text_input(f"{iname} - {title}", value="")


def execute_calculator(calc_code, test_inputs, st):
    """
    执行计算器代码并返回结果

    Args:
        calc_code: 要执行的计算器代码
        test_inputs: 输入参数字典
        st: Streamlit 对象，用于显示结果

    Returns:
        tuple: (计算结果字典, 是否成功)
    """
    try:
        # 初始化Excel环境并预填充单元格
        app, wb, sheet = init_excel_sheet(test_inputs)

        # 准备运行环境
        local_ns = {
            "sheet": sheet,
            "plt": plt,
            **test_inputs,  # 仍然保留原始输入以供代码使用
        }

        # 执行代码
        exec(calc_code, local_ns, local_ns)

        # 获取结果
        calc_result = format_calc_result(local_ns.get("result", None))

        # 检查是否有图表输出
        if plt.get_fignums():
            calc_result["plot"] = save_plot_as_base64()

        # 显示结果
        if calc_result["type"] == "single":
            st.write("结果:", calc_result["value"])
        elif calc_result["type"] == "multiple":
            st.write("结果:")
            for i, val in enumerate(calc_result["values"]):
                st.write(f"{i+1}.", val)

        if "plot" in calc_result:
            st.image(f"data:image/png;base64,{calc_result['plot']}")

        return calc_result, True

    except Exception as e:
        import traceback

        traceback.print_exc()
        st.error(f"执行错误: {e}")
        return None, False
    finally:
        # 清理Excel资源
        cleanup_excel(app, wb)


def display_calculation_history(tasks, show_username=False):
    """
    通用的计算历史记录显示函数

    Args:
        tasks: 计算任务列表
        show_username: 是否显示用户名
    """
    # 如果没有记录，直接返回
    if not tasks:
        st.info("暂无记录")
        return

    # 每页显示的记录数
    items_per_page = 10
    total_items = len(tasks)

    # 分页控件
    current_page = sac.pagination(
        total=total_items,
        page_size=items_per_page,
        align='center',
        show_total=True,
        previous="上一页",
        next="下一页",
        key="history_pagination"
    )

    # 计算当前页的数据范围
    start_idx = (current_page - 1) * items_per_page
    end_idx = min(start_idx + items_per_page, total_items)

    # 获取当前页的任务
    page_tasks = tasks[start_idx:end_idx]

    # 显示当前页的记录
    for t in page_tasks:
        # 构建标题，根据是否显示用户名调整格式
        title = f"{t['calculator_name']} | {t['timestamp']} | CT-{t['task_id']:05d}"
        if show_username:
            title = f"{title} | 用户: {t['username']}"

        with st.expander(title):
            st.write("**输入**:")
            # 创建一个包含输入项名称和值的数据帧，使用title作为列名
            input_data = pd.DataFrame(
                {
                    "参数名": list(t["inputs"].keys()),  # 这里的keys已经是title了
                    "输入值": [str(v) for v in t["inputs"].values()],
                }
            )
            st.dataframe(input_data, use_container_width=True, hide_index=True)

            st.write("**输出**:")
            if isinstance(t["output"], dict):
                if t["output"]["type"] == "single":
                    st.write(t["output"]["value"])
                elif t["output"]["type"] == "multiple":
                    for i, val in enumerate(t["output"]["values"]):
                        st.write(f"{i+1}.", val)
                if "plot" in t["output"]:
                    st.image(f"data:image/png;base64,{t['output']['plot']}")
            else:
                st.write(t["output"])

            # 添加PDF导出按钮
            generate_pdf_download_button(
                st,
                task_id=t["task_id"],
                button_text="导出为PDF"
            )


def edit_calc_page(calc_id):
    """编辑计算器"""
    calc = load_calculator_by_id(calc_id)
    if not calc:
        st.warning(f"未找到计算器 ID={calc_id}")
        return

    with st.container(key="calc_info"):
        st.subheader(f"{calc.name}")
        status = calc.status
        sac.tags(
            [
                sac.Tag(
                    label=status,
                    color=status_colors.get(status, "blue"),
                    icon=status_icon.get(status, sac.BsIcon(name="question-lg")),
                ),
                sac.Tag(
                    label=f"流水号: C-{calc_id:05d}",
                    color="blue",
                    icon=sac.BsIcon("hash"),
                ),
                sac.Tag(label=f"版本: {calc.version}", icon=sac.BsIcon("box")),
                sac.Tag(
                    label=f"创建: {calc.created_at.strftime('%Y-%m-%d %H:%M')}",
                    icon=sac.BsIcon("calendar-plus"),
                ),
                sac.Tag(
                    label=f"更新: {calc.updated_at.strftime('%Y-%m-%d %H:%M')}",
                    icon=sac.BsIcon("calendar-check"),
                ),
            ]
        )

    # 根据用户角色显示不同的标签页
    if "sysadmin" in st.session_state.roles:
        tabs = ["查看详情", "编辑", "权限配置", "计算历史", "操作记录"]
    elif "calcadmin" in st.session_state.roles:
        tabs = ["查看详情", "编辑", "计算历史", "操作记录"]
    elif "statusadmin" in st.session_state.roles:
        tabs = ["查看详情", "修改状态", "计算历史", "操作记录"]
    else:
        tabs = ["查看详情", "计算历史"]

    tabs = st.tabs(tabs)

    # --- 查看详情 ---
    with tabs[0]:
        # 导出PDF按钮
        try:
            from pdf_utils import create_calculator_code_pdf
            pdf_buffer = create_calculator_code_pdf(calc)
            current_time = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
            filename = f"{calc.name}_配置文档_{current_time}.pdf"

            st.download_button(
                label="下载PDF文档",
                data=pdf_buffer,
                file_name=filename,
                mime="application/pdf",
                key=f"download_calc_pdf_{calc_id}"
            )
        except Exception as e:
            import traceback
            traceback.print_exc()
            st.error(f"生成PDF文档失败：{e}")
        st.markdown("**计算公式**:")
        st.code(calc.code, language="python")
        st.markdown("**输入配置**:")

        input_df = pd.DataFrame(calc.inputs).fillna("")  # 处理 None 值
        column_config_map = {}
        for col in input_df.columns:
            if input_df[col].dtype in ["float64", "int64"]:
                column_config_map[col] = st.column_config.NumberColumn(
                    col, width="fit-content", help="输入参数配置"
                )
            else:
                column_config_map[col] = st.column_config.TextColumn(
                    col, width="fit-content", help="输入参数配置"
                )

        st.data_editor(
            input_df,
            disabled=True,  # 设置为不可编辑
            use_container_width=True,
            column_config=column_config_map,
            hide_index=True,
        )

    # --- 编辑 ---
    if (
        any(role in st.session_state.roles for role in ["calcadmin", "sysadmin"])
        and len(tabs) > 1
    ):
        with tabs[1]:
            if calc.status != "draft":
                st.warning(
                    "⚠️ 当前计算器不处于草稿状态，无法编辑。请先将状态修改为 draft。"
                )
                st.info("提示：请联系质检人员将计算器状态修改为 draft 后再进行编辑。")
            else:
                schema_mode = st.radio(
                    "选择编辑输入参数的方式",
                    ["图形界面", "JSON模式"],
                    key=f"edit_schema_mode_{calc_id}",
                )

                state_key = f"edit_parsed_inputs_{calc_id}"
                if state_key not in st.session_state:
                    # 确保加载的计算器配置中有target字段
                    st.session_state[state_key] = ensure_target_field(calc.inputs)

                if schema_mode == "JSON模式":
                    current_json_text = json.dumps(
                        st.session_state[state_key], ensure_ascii=False, indent=2
                    )
                    input_str = st.text_area(
                        "输入参数配置（JSON数组）",
                        value=current_json_text,
                        height=150,
                        key=f"edit_input_str_json_{calc_id}",
                    )
                    if st.button("刷新输入输出 (编辑)"):
                        try:
                            st.session_state[state_key] = json.loads(input_str)
                            st.rerun()
                        except Exception as e:
                            st.error(f"JSON 解析失败：{e}")
                    parsed_inputs = st.session_state[state_key]

                else:
                    st.info(
                        "输入字段设置完毕后，请点击下面的刷新按钮来刷新显示的输入控件"
                    )
                    # 添加 target 列的配置
                    column_config = {
                        "name": "变量名",
                        "title": "标题",
                        "input_mode": st.column_config.SelectboxColumn(
                            "输入类型", options=["输入项", "非输入项"], default="输入项"
                        ),
                        "type": st.column_config.SelectboxColumn(
                            "数据类型",
                            options=["number", "integer", "string"],
                            default="string",
                        ),
                        "target": "计算对象",  # 新增 target 列
                        "minimum": "最小值",
                        "maximum": "最大值",
                        "step": "有效位数",
                        "default": "默认值",
                    }

                    data_editor_value = st.data_editor(
                        st.session_state[state_key],
                        key=f"edit_data_editor_{calc_id}",
                        use_container_width=True,
                        num_rows="dynamic",
                        column_config=column_config,
                    )
                    if st.button("刷新输入输出 (编辑)"):
                        st.session_state[state_key] = data_editor_value
                        st.rerun()
                    parsed_inputs = st.session_state[state_key]

                with st.form(f"edit_calc_form_{calc_id}"):
                    new_name = st.text_input("计算器名称", value=calc.name)
                    new_code = code_editor(
                        code=calc.code,
                        height=20,
                        response_mode="debounce",
                        lang="python",
                        buttons=code_save_button_config,
                    )["text"]

                    st.write("#### 测试输入")
                    test_inputs = {}

                    # 收集所有不同的 target，并创建 tabs
                    targets = set()
                    for inp in parsed_inputs:
                        target = inp.get("target", "其他")
                        targets.add(target)

                    input_fields_by_target = {}
                    for inp in parsed_inputs:
                        target = inp.get("target", "其他")
                        if target is None:
                            target = "其他"
                        if target not in input_fields_by_target:
                            input_fields_by_target[target] = []
                        input_fields_by_target[target].append(inp)

                    # 如果只有一个 target，不创建 tabs
                    if len(targets) <= 1:
                        # 修改为每行两个输入字段
                        fields = parsed_inputs
                        for i in range(0, len(fields), 2):
                            col1, col2 = st.columns(2)
                            # 渲染第一个字段
                            render_input_field(fields[i], test_inputs, col1)
                            # 如果有第二个字段，渲染它
                            if i + 1 < len(fields):
                                render_input_field(fields[i + 1], test_inputs, col2)
                    else:
                        # 创建 tabs，使用不同的变量名
                        input_group_tabs = st.tabs(sort_targets(targets))
                        # 在每个 tab 中显示对应的输入字段
                        for i, target in enumerate(sort_targets(targets)):
                            with input_group_tabs[i]:
                                # 获取当前target的所有字段
                                target_fields = input_fields_by_target[target]

                                # 创建足够的行来容纳所有字段
                                for j in range(0, len(target_fields), 2):
                                    col1, col2 = st.columns(2)
                                    # 渲染第一个字段
                                    render_input_field(
                                        target_fields[j], test_inputs, col1
                                    )
                                    # 如果有第二个字段，渲染它
                                    if j + 1 < len(target_fields):
                                        render_input_field(
                                            target_fields[j + 1], test_inputs, col2
                                        )

                    btn_test = st.form_submit_button("测试运行 (编辑)")
                    btn_save = st.form_submit_button("保存修改 (编辑)")

                    if btn_test:
                        calc_result, success = execute_calculator(
                            new_code, test_inputs, st
                        )
                        if success:
                            st.toast("测试成功!")

                    if btn_save:
                        update_data = {
                            "name": new_name,
                            "code": new_code,
                            "inputs": ensure_target_field(parsed_inputs),
                            "status": "draft",
                        }

                        st.toast(
                            "修改已保存！计算器状态已自动设置为 inactive，请联系质检人员审核。"
                        )
                        try:
                            update_calculator(calc_id, update_data)
                            st.toast("计算器已更新")
                        except Exception as e:
                            st.error(f"更新计算器时出错：{e}")

                        st.rerun()

    # --- 权限配置 ---
    if "sysadmin" in st.session_state.roles:
        perm_tab_index = 2
        with tabs[perm_tab_index]:
            new_access_type = st.radio(
                "访问权限类型",
                ["所有用户可访问", "仅指定用户可访问"],
                index=0 if calc.access_control["type"] == "all" else 1,
                help="选择'所有用户可访问'时，包括将来新增的用户也可以使用此计算器",
            )

            config = load_config()
            new_access = {
                "type": "all" if new_access_type == "所有用户可访问" else "restricted",
                "allowed_users": calc.access_control.get("allowed_users", []),
                "reviewers": calc.access_control.get("reviewers", []),  # 添加复核员配置
            }

            # 获取所有用户列表
            all_users = list(config["credentials"]["usernames"].keys())

            if new_access["type"] == "restricted":
                # 选择可访问的用户
                new_access["allowed_users"] = st.multiselect(
                    "选择可访问的用户",
                    options=all_users,
                    default=calc.access_control.get("allowed_users", []),
                    help="只有被选中的用户可以使用此计算器",
                )
                # 显示当前选择的用户数量
                st.info(f"当前已选择 {len(new_access['allowed_users'])} 个用户")

            # 添加计算复核员配置
            st.write("#### 计算复核员配置")
            new_access["reviewers"] = st.multiselect(
                "选择计算复核员",
                options=all_users,
                default=calc.access_control.get("reviewers", []),
                help="计算复核员可以查看该计算器下所有计算任务的具体信息",
            )
            if new_access["reviewers"]:
                st.info(f"当前已选择 {len(new_access['reviewers'])} 个复核员")

            if st.button("保存权限设置"):
                try:
                    update_calculator(calc_id, {"access_control": new_access})
                    st.toast("权限设置已更新")
                    st.rerun()
                except Exception as e:
                    st.error(f"更新权限失败：{e}")

    # --- 计算历史 ---
    # 根据角色确定历史记录标签页的索引
    if "sysadmin" in st.session_state.roles:
        history_tab_index = 3
    elif "calcadmin" in st.session_state.roles:
        history_tab_index = 2
    elif "statusadmin" in st.session_state.roles:
        history_tab_index = 2
    else:
        history_tab_index = 1

    with tabs[history_tab_index]:
        st.write("#### 计算历史记录")

        # 从数据库加载当前计算器的历史记录
        calc_history = load_tasks(calculator_id=calc_id)

        if not calc_history:
            st.info("暂无计算记录")
        else:
            # 时间范围筛选
            col1, col2 = st.columns(2)
            with col1:
                start_date = st.date_input(
                    "开始日期", value=None, key=f"admin_history_start_date_{calc_id}"
                )
            with col2:
                end_date = st.date_input(
                    "结束日期", value=None, key=f"admin_history_end_date_{calc_id}"
                )

            # 用户筛选
            col1, col2 = st.columns(2)
            with col1:
                if any(
                    role in st.session_state.roles
                    for role in ["admin", "sysadmin", "calcadmin"]
                ):
                    all_users = list({t["username"] for t in calc_history})
                    user_filter = st.selectbox(
                        "按用户筛选",
                        ["(全部)"] + all_users,
                        key=f"admin_user_filter_{calc_id}",
                    )

            # 输入值筛选
            st.write("按输入输出值筛选")
            col1, col2, col3 = st.columns(3)
            with col1:
                # 获取所有可能的输入字段
                input_fields = set()
                for task in calc_history:
                    input_fields.update(task["inputs"].keys())
                filter_type = st.radio(
                    "筛选类型", ["输入", "输出"], key=f"admin_filter_type_{calc_id}"
                )
            with col2:
                if filter_type == "输入":
                    filter_field = st.selectbox(
                        "选择输入字段",
                        ["(无)"] + list(input_fields),
                        key=f"admin_filter_field_{calc_id}",
                    )
            with col3:
                if filter_type == "输入" and filter_field != "(无)":
                    filter_value = st.text_input(
                        "值包含", key=f"admin_filter_value_{calc_id}"
                    )
                elif filter_type == "输出":
                    filter_value = st.text_input(
                        "输出值包含", key=f"admin_filter_output_{calc_id}"
                    )

            # 应用筛选条件
            filtered = calc_history

            # 应用时间筛选
            if start_date:
                filtered = [
                    t
                    for t in filtered
                    if datetime.datetime.strptime(
                        t["timestamp"].split()[0], "%Y-%m-%d"
                    ).date()
                    >= start_date
                ]
            if end_date:
                filtered = [
                    t
                    for t in filtered
                    if datetime.datetime.strptime(
                        t["timestamp"].split()[0], "%Y-%m-%d"
                    ).date()
                    <= end_date
                ]

            # 应用用户筛选
            if user_filter != "(全部)":
                filtered = [t for t in filtered if t["username"] == user_filter]

            # 应用输入输出值筛选
            if filter_type == "输入" and filter_field != "(无)" and filter_value:
                filtered = [
                    t
                    for t in filtered
                    if str(t["inputs"].get(filter_field, "")).find(filter_value) != -1
                ]
            elif filter_type == "输出" and filter_value:
                filtered = [
                    t for t in filtered if str(t["output"]).find(filter_value) != -1
                ]

            # 显示过滤后的记录
            st.markdown(f"找到 {len(filtered)} 条记录")
            display_calculation_history(filtered, show_username=True)

            # 导出功能
            if st.button("导出筛选结果为CSV"):
                import io
                import csv

                csv_buffer = io.StringIO()
                fieldnames = ["task_id", "username", "timestamp", "inputs", "output"]
                writer = csv.DictWriter(csv_buffer, fieldnames=fieldnames)
                writer.writeheader()
                for t in filtered:
                    writer.writerow(
                        {
                            "task_id": t["task_id"],
                            "username": t["username"],
                            "timestamp": t["timestamp"],
                            "inputs": json.dumps(t["inputs"], ensure_ascii=False),
                            "output": t["output"],
                        }
                    )
                csv_data = csv_buffer.getvalue().encode("utf-8")
                st.download_button(
                    label="下载CSV文件",
                    data=csv_data,
                    file_name=f"calc_{calc_id}_history.csv",
                    mime="text/csv",
                )

    # --- 操作记录 tab ---
    # 根据角色确定审计日志标签页的索引
    if "sysadmin" in st.session_state.roles:
        audit_tab_index = 4
    elif "calcadmin" in st.session_state.roles:
        audit_tab_index = 3
    elif "statusadmin" in st.session_state.roles:
        audit_tab_index = 3
    else:
        audit_tab_index = None

    if audit_tab_index is not None:
        with tabs[audit_tab_index]:
            st.write("#### 操作记录")

            # 获取操作记录
            audit_logs = get_calc_audit_logs(calc_id)

            if not audit_logs:
                st.info("暂无操作记录")
            else:
                # 时间范围筛选
                col1, col2 = st.columns(2)
                with col1:
                    start_date = st.date_input(
                        "开始日期", value=None, key=f"audit_start_date_{calc_id}"
                    )
                with col2:
                    end_date = st.date_input(
                        "结束日期", value=None, key=f"audit_end_date_{calc_id}"
                    )

                # 获取所有操作用户列表
                all_users = list(set(log["username"] for log in audit_logs))

                # 用户筛选
                user_filter = st.selectbox(
                    "按用户筛选",
                    ["(全部)"] + all_users,
                    key=f"audit_user_filter_{calc_id}",
                )

                # 操作类型筛选
                all_actions = list(set(log["action"] for log in audit_logs))
                action_filter = st.selectbox(
                    "按操作类型筛选",
                    ["(全部)"] + all_actions,
                    key=f"audit_action_filter_{calc_id}",
                )

                # 应用筛选条件
                filtered_logs = audit_logs

                if start_date:
                    filtered_logs = [
                        log
                        for log in filtered_logs
                        if datetime.datetime.strptime(log["date"], "%Y-%m-%d").date()
                        >= start_date
                    ]
                if end_date:
                    filtered_logs = [
                        log
                        for log in filtered_logs
                        if datetime.datetime.strptime(log["date"], "%Y-%m-%d").date()
                        <= end_date
                    ]
                if user_filter != "(全部)":
                    filtered_logs = [
                        log for log in filtered_logs if log["username"] == user_filter
                    ]
                if action_filter != "(全部)":
                    filtered_logs = [
                        log for log in filtered_logs if log["action"] == action_filter
                    ]

                # 显示筛选结果统计
                st.write(f"共找到 {len(filtered_logs)} 条记录")

                # 使用数据表格显示基本信息
                log_table = []
                for log in filtered_logs:
                    log_table.append(
                        {
                            "时间": f"{log['date']} {log['time']}",
                            "操作者": log["username"],
                            "操作类型": log["action"],
                            "详情": log["details"],
                        }
                    )

                st.dataframe(pd.DataFrame(log_table), use_container_width=True)

                # 使用选择框显示详细信息
                if any(
                    log.get("old_value") or log.get("new_value")
                    for log in filtered_logs
                ):
                    st.write("#### 修改详情")
                    selected_log = st.selectbox(
                        "选择记录查看详细修改内容",
                        options=[
                            f"{log['date']} {log['time']} | {log['username']} | {log['action']}"
                            for log in filtered_logs
                        ],
                        key=f"audit_detail_selector_{calc_id}",
                    )

                    if selected_log:
                        idx = [
                            f"{log['date']} {log['time']} | {log['username']} | {log['action']}"
                            for log in filtered_logs
                        ].index(selected_log)
                        log = filtered_logs[idx]

                        # 处理状态变更
                        old_status = log.get("old_value", "")
                        new_status = log.get("new_value", "")
                        if isinstance(old_status, str) and isinstance(new_status, str):
                            # 如果是简单的状态变更
                            st.write(f"**修改前状态：** {old_status}")
                            st.write(f"**修改后状态：** {new_status}")
                        else:
                            # 如果是完整的配置变更
                            col1, col2 = st.columns(2)
                            with col1:
                                st.write("**修改前**")
                                if old_status:
                                    if "name" in old_status:
                                        st.write(f"名称: {old_status['name']}")
                                    if "code" in old_status:
                                        st.write("代码:")
                                        st.code(old_status["code"], language="python")
                                    if "inputs" in old_status:
                                        st.write("输入参数:")
                                        st.dataframe(pd.DataFrame(old_status["inputs"]))

                            with col2:
                                st.write("**修改后**")
                                if new_status:
                                    if "name" in new_status:
                                        st.write(f"名称: {new_status['name']}")
                                    if "code" in new_status:
                                        st.write("代码:")
                                        st.code(new_status["code"], language="python")
                                    if "inputs" in new_status:
                                        st.write("输入参数:")
                                        st.dataframe(pd.DataFrame(new_status["inputs"]))

                # 导出功能
                if st.button("导出操作记录"):
                    csv_buffer = io.StringIO()
                    fieldnames = ["timestamp", "username", "action", "details"]
                    writer = csv.DictWriter(csv_buffer, fieldnames=fieldnames)
                    writer.writeheader()
                    for log in filtered_logs:
                        writer.writerow(
                            {
                                "timestamp": f"{log['date']} {log['time']}",
                                "username": log["username"],
                                "action": log["action"],
                                "details": log["details"],
                            }
                        )
                    csv_data = csv_buffer.getvalue().encode("utf-8")
                    st.download_button(
                        label="下载CSV文件",
                        data=csv_data,
                        file_name=f"calc_{calc_id}_audit_log.csv",
                        mime="text/csv",
                    )
